from object import Object
from cube import Cube
from eventServer import eventServer
from gameServer import gameServer
from vec3 import Vec3

import random
import math

class ParticleEffect(Object):
    def __init__(self):
        Object.__init__(self)
        
        self.defaultVar("numParticles",20)
        self.defaultVar("minLifetime",1.0)
        self.defaultVar("maxLifetime",3.0)
        self.defaultVar("minr",1.0)
        self.defaultVar("maxr",3.0)
        self.defaultVar("continuous",False)
        self.defaultVar("moveOut",True)
        self.defaultVar("particleSize",1.0)
        self.defaultVar("timeScale",True)
        self.defaultVar("pos",Vec3())
        self.defaultVar("texture","")
        self.defaultVar("emitRate",5.0)
        self.defaultVar("minDth",-2.0)
        self.defaultVar("maxDth",2.0)
        
        self.startTime = None
        self.lifetime = None
        self.emitTime = None
        self.particles = []
        
        eventServer.register("update",self.update)
        
    def update(self, cmd, args):
        time = args['time']
        dtime = args['dtime']
        
        firstFrame = False
        if not self.startTime:
            firstFrame = True
            self.startTime = time
            
        if not self.lifetime:
            self.lifetime = random.uniform(self.getVar("minLifetime"),self.getVar("maxLifetime"))
            
        #print self.getVar("name"), time - self.startTime, self.lifetime
            
        if not self.getVar("continuous") and time - self.startTime > self.lifetime:
            #print "kill"
            for particleName in self.particles:
                gameServer.removeObject(particleName)
            gameServer.removeObject(self.getVar("name"))
            return
            
        if firstFrame and not self.getVar("continuous"):
            for i in range(self.getVar("numParticles")):
                self.particles.append(self.makeParticle())
                
        if self.getVar("continuous"):
            if len(self.particles) < self.getVar("numParticles"):
                if not self.emitTime:
                    self.emitTime = 0
                    
                self.emitTime += dtime
                if self.emitTime > 1.0 / self.getVar("emitRate"):
                    self.makeParticle()
                    self.emitTime = 0
                
        toRemove = []
        for particleName in self.particles:
            particle = gameServer.getObject(particleName)
            if particle:
                timeRatio = (time - self.startTime) / self.lifetime
                if self.getVar("moveOut"):
                    r = timeRatio * particle.getVar("r")
                    scale = (1.0 - timeRatio) * self.getVar("particleSize")
                    color = 1.0 - timeRatio
                else:
                    r = (1.0 - timeRatio) * particle.getVar("r")
                    scale = timeRatio * self.getVar("particleSize")
                    color = timeRatio
                    
                th = particle.getVar("th")
                particle.setVar("th",th + particle.getVar("dth") * dtime)
                particle.setVar("rot",th+math.pi)
                x = r * math.cos(th)
                y = r * math.sin(th)
                particle.setVar("pos",self.getVar("pos") + Vec3(x,y))
                particle.setVar("scale",Vec3(scale,scale,scale))
                
                particle.setVar("color",(color,color,color))
                
                #print particleName, particle.getVar("pos"), particle.getVar("scale")
            else:
                toRemove.append(particleName)
                
        for particleName in toRemove:
            #print "remove", particleName
            self.particles.remove(particleName)
            
    def makeParticle(self):
        particleName = gameServer.makeObjectName(self.getVar("name") + "_particle")
        particle = gameServer.addObject(particleName,Cube())
        
        particle.setVar("r",random.uniform(self.getVar("minr"),self.getVar("maxr")))
            
        particle.setVar("dth",random.uniform(self.getVar("minDth"),self.getVar("maxDth")))
        particle.setVar("th",random.uniform(-math.pi,math.pi))
        particle.setVar("texture",self.getVar("texture"))
        
        return particleName
